/* 
 * PS3 Teensy HID Gamepad
 * Copyright (C) 2010 Josh Kropf <josh@slashdev.ca>
 *
 * Based on works by:
 *   grunskis <http://github.com/grunskis/gamepad>
 *   Toodles <http://forums.shoryuken.com/showthread.php?t=131230>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/* USB Keyboard Example for Teensy USB Development Board
 * http://www.pjrc.com/teensy/usb_keyboard.html
 * Copyright (c) 2009 PJRC.COM, LLC
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#define USB_GAMEPAD_PRIVATE_INCLUDE

#include "usb_gamepad.h"

/**************************************************************************
 *
 *  Configurable Options
 *
 **************************************************************************/

// You can change these to give your code its own name.
#define STR_MANUFACTURER	L"OpenChord X RMIT Exertion Games Lab"
#define STR_PRODUCT			L"UnoJoy Joystick"
//#define STR_MANUFACTURER	L"SEGA"
//#define STR_PRODUCT		L"VIRTUA STICK High Grade"


// Mac OS-X and Linux automatically load the correct drivers.  On
// Windows, even though the driver is supplied by Microsoft, an
// INF file is needed to load the driver.  These numbers need to
// match the INF file.
#define VENDOR_ID		0x10C4
#define PRODUCT_ID		0x82C0


// USB devices are supposed to implement a halt feature, which is
// rarely (if ever) used.  If you comment this line out, the halt
// code will be removed, saving 102 bytes of space (gcc 4.3.0).
// This is not strictly USB compliant, but works with all major
// operating systems.
//#define SUPPORT_ENDPOINT_HALT



/**************************************************************************
 *
 *  Endpoint Buffer Configuration
 *
 **************************************************************************/

#define ENDPOINT0_SIZE	64

#define GAMEPAD_INTERFACE	0
#define GAMEPAD_ENDPOINT	1
#define GAMEPAD_SIZE		64
#define GAMEPAD_BUFFER	EP_SINGLE_BUFFER //EP_DOUBLE_BUFFER

static const uint8_t PROGMEM endpoint_config_table[] = {
	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(GAMEPAD_SIZE) | GAMEPAD_BUFFER,
	0,
	0,
	0
};


/**************************************************************************
 *
 *  Descriptor Data
 *
 **************************************************************************/

// Descriptors are the data that your computer reads when it auto-detects
// this USB device (called "enumeration" in USB lingo).  The most commonly
// changed items are editable at the top of this file.  Changing things
// in here should only be done by those who've read chapter 9 of the USB
// spec and relevant portions of any USB class specifications!


static const uint8_t PROGMEM device_descriptor[] = {
	18,					// bLength                         IS THIS CORRECT?
	1,					// bDescriptorType
	0x10, 0x01,				// bcdUSB
	0,					// bDeviceClass
	0,					// bDeviceSubClass
	0,					// bDeviceProtocol
	ENDPOINT0_SIZE,				// bMaxPacketSize0
	LSB(VENDOR_ID), MSB(VENDOR_ID),		// idVendor
	LSB(PRODUCT_ID), MSB(PRODUCT_ID),	// idProduct
	0x00, 0x01,				// bcdDevice
	1,					// iManufacturer
	2,					// iProduct
	0,					// iSerialNumber
	1					// bNumConfigurations
};

static const uint8_t PROGMEM gamepad_hid_report_desc[] = {
	0x05, 0x01,        // USAGE_PAGE (Generic Desktop)
	0x09, 0x05,        // USAGE (Gamepad)
	0xa1, 0x01,        // COLLECTION (Application)
	0x15, 0x00,        //   LOGICAL_MINIMUM (0)
	0x25, 0x01,        //   LOGICAL_MAXIMUM (1)
	0x35, 0x00,        //   PHYSICAL_MINIMUM (0)
	0x45, 0x01,        //   PHYSICAL_MAXIMUM (1)
	0x75, 0x01,        //   REPORT_SIZE (1)
	0x95, 0x80,        //   REPORT_COUNT (128)
	0x05, 0x09,        //   USAGE_PAGE (Button)
	0x19, 0x01,        //   USAGE_MINIMUM (Button 1)
	0x29, 0x80,        //   USAGE_MAXIMUM (Button 128)
	0x81, 0x02,        //   INPUT (Data,Var,Abs)         
	0x05, 0x01,        //   USAGE_PAGE (Generic Desktop)    
	0x26, 0xff, 0x00,  //   LOGICAL_MAXIMUM (255)
	0x46, 0xff, 0x00,  //   PHYSICAL_MAXIMUM (255)       
	0x09, 0x30,        //   USAGE (X)
	0x09, 0x31,        //   USAGE (Y)
	0x09, 0x32,        //   USAGE (Z)
	0x09, 0x35,        //   USAGE (Rz)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider) 
  0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
  0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
  0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
  0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
  0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
  0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
  0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
  0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)
	0x09, 0x36,        //   USAGE (Slider)   
	0x75, 0x08,        //   REPORT_SIZE (8)
	0x95, 0x30,        //   REPORT_COUNT (48)
	0xc0               // END_COLLECTION
};


#define CONFIG1_DESC_SIZE		(9+9+9+7)
#define GAMEPAD_HID_DESC_OFFSET	(9+9)
static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
	// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
	9, 					// bLength;
	2,					// bDescriptorType;
	LSB(CONFIG1_DESC_SIZE),			// wTotalLength
	MSB(CONFIG1_DESC_SIZE),
	1,					// bNumInterfaces
	1,					// bConfigurationValue
	0,					// iConfiguration
	0x80,					// bmAttributes
	50,					// bMaxPower
	// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
	9,					// bLength
	4,					// bDescriptorType
	GAMEPAD_INTERFACE,			// bInterfaceNumber
	0,					// bAlternateSetting
	1,					// bNumEndpoints
	0x03,					// bInterfaceClass (0x03 = HID)
	0x00,					// bInterfaceSubClass (0x00 = No Boot)
	0x00,					// bInterfaceProtocol (0x00 = No Protocol)
	0,					// iInterface
	// HID interface descriptor, HID 1.11 spec, section 6.2.1
	9,					// bLength
	0x21,					// bDescriptorType
	0x11, 0x01,				// bcdHID
	0,					// bCountryCode
	1,					// bNumDescriptors
	0x22,					// bDescriptorType
	sizeof(gamepad_hid_report_desc),	// wDescriptorLength
	0,
	// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
	7,					// bLength
	5,					// bDescriptorType
	GAMEPAD_ENDPOINT | 0x80,		// bEndpointAddress
	0x03,					// bmAttributes (0x03=intr)
	GAMEPAD_SIZE, 0,			// wMaxPacketSize
	10					// bInterval
};

// If you're desperate for a little extra code memory, these strings
// can be completely removed if iManufacturer, iProduct, iSerialNumber
// in the device desciptor are changed to zeros.
struct usb_string_descriptor_struct {
	uint8_t bLength;
	uint8_t bDescriptorType;
	int16_t wString[];
};
static const struct usb_string_descriptor_struct PROGMEM string0 = {
	4,
	3,
	{0x0409}
};
static const struct usb_string_descriptor_struct PROGMEM string1 = {
	sizeof(STR_MANUFACTURER),
	3,
	STR_MANUFACTURER
};
static const struct usb_string_descriptor_struct PROGMEM string2 = {
	sizeof(STR_PRODUCT),
	3,
	STR_PRODUCT
};

// This table defines which descriptor data is sent for each specific
// request from the host (in wValue and wIndex).
static const struct descriptor_list_struct {
	uint16_t	wValue;
	uint16_t	wIndex;
	const uint8_t	*addr;
	uint8_t		length;
} PROGMEM descriptor_list[] = {
	{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
	{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
	{0x2100, GAMEPAD_INTERFACE, config1_descriptor+GAMEPAD_HID_DESC_OFFSET, 9},
	{0x2200, GAMEPAD_INTERFACE, gamepad_hid_report_desc, sizeof(gamepad_hid_report_desc)},
	{0x0300, 0x0000, (const uint8_t *)&string0, 4},
	{0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
	{0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}
};
#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))


/**************************************************************************
 *
 *  Variables - these are the only non-stack RAM usage
 *
 **************************************************************************/

// zero when we are not configured, non-zero when enumerated
static volatile uint8_t usb_configuration = 0;

static const gamepad_state_t PROGMEM gamepad_idle_state = {
	.b0_btn = 0, .b1_btn = 0, .b2_btn = 0, .b3_btn = 0,
	.b4_btn = 0, .b5_btn = 0, .b6_btn = 0, .b7_btn = 0,
	.b8_btn = 0, .b9_btn = 0, .b10_btn = 0, .b11_btn = 0,
	.b12_btn = 0, .b13_btn = 0, .b14_btn = 0, .b15_btn = 0,
	.b16_btn = 0, .b17_btn = 0, .b18_btn = 0, .b19_btn = 0,
	.b20_btn = 0, .b21_btn = 0, .b22_btn = 0, .b23_btn = 0,
	.b24_btn = 0, .b25_btn = 0, .b26_btn = 0, .b27_btn = 0,
	.b28_btn = 0, .b29_btn = 0, .b30_btn = 0, .b31_btn = 0,
	.b32_btn = 0, .b33_btn = 0, .b34_btn = 0, .b35_btn = 0,
	.b36_btn = 0, .b37_btn = 0, .b38_btn = 0, .b39_btn = 0,
	.b40_btn = 0, .b41_btn = 0, .b42_btn = 0, .b43_btn = 0,
	.b44_btn = 0, .b45_btn = 0, .b46_btn = 0, .b47_btn = 0,
	.b48_btn = 0, .b49_btn = 0, .b50_btn = 0, .b51_btn = 0,
	.b52_btn = 0, .b53_btn = 0, .b54_btn = 0, .b55_btn = 0,
	.b56_btn = 0, .b57_btn = 0, .b58_btn = 0, .b59_btn = 0,
	.b60_btn = 0, .b61_btn = 0, .b62_btn = 0, .b63_btn = 0,
	.b64_btn = 0, .b65_btn = 0, .b66_btn = 0, .b67_btn = 0,
	.b68_btn = 0, .b69_btn = 0, .b70_btn = 0, .b71_btn = 0,
	.b72_btn = 0, .b73_btn = 0, .b74_btn = 0, .b75_btn = 0,
	.b76_btn = 0, .b77_btn = 0, .b78_btn = 0, .b79_btn = 0,
	.b80_btn = 0, .b81_btn = 0, .b82_btn = 0, .b83_btn = 0,
	.b84_btn = 0, .b85_btn = 0, .b86_btn = 0, .b87_btn = 0,
	.b88_btn = 0, .b89_btn = 0, .b90_btn = 0, .b91_btn = 0,
	.b92_btn = 0, .b93_btn = 0, .b94_btn = 0, .b95_btn = 0,
	.b96_btn = 0, .b97_btn = 0, .b98_btn = 0, .b99_btn = 0,
	.b100_btn = 0, .b101_btn = 0, .b102_btn = 0, .b103_btn = 0,
	.b104_btn = 0, .b105_btn = 0, .b106_btn = 0, .b107_btn = 0,
	.b108_btn = 0, .b109_btn = 0, .b110_btn = 0, .b111_btn = 0,
	.b112_btn = 0, .b113_btn = 0, .b114_btn = 0, .b115_btn = 0,
	.b116_btn = 0, .b117_btn = 0, .b118_btn = 0, .b119_btn = 0,					
	.b120_btn = 0, .b121_btn = 0, .b122_btn = 0, .b123_btn = 0,
	.b124_btn = 0, .b125_btn = 0, .b126_btn = 0, .b127_btn = 0,	
	
	.a0_axis = 0x80, .a1_axis = 0x80, .a2_axis = 0x80, .a3_axis = 0x80,
	.a4_axis = 0x80, .a5_axis = 0x80, .a6_axis = 0x80, .a7_axis = 0x80,
	.a8_axis = 0x80, .a9_axis = 0x80, .a10_axis = 0x80, .a11_axis = 0x80, 
	.a12_axis = 0x80, .a13_axis = 0x80, .a14_axis = 0x80, .a15_axis = 0x80, 
	.a16_axis = 0x80, .a17_axis = 0x80, .a18_axis = 0x80, .a19_axis = 0x80, 
	.a20_axis = 0x80, .a21_axis = 0x80, .a22_axis = 0x80, .a23_axis = 0x80,
	.a24_axis = 0x80, .a25_axis = 0x80, .a26_axis = 0x80, .a27_axis = 0x80,
	.a28_axis = 0x80, .a29_axis = 0x80, .a30_axis = 0x80, .a31_axis = 0x80,
	.a32_axis = 0x80, .a33_axis = 0x80, .a34_axis = 0x80, .a35_axis = 0x80,
	.a36_axis = 0x80, .a37_axis = 0x80, .a38_axis = 0x80, .a39_axis = 0x80,
	.a40_axis = 0x80, .a41_axis = 0x80, .a42_axis = 0x80, .a43_axis = 0x80,
	.a44_axis = 0x80, .a45_axis = 0x80, .a46_axis = 0x80, .a47_axis = 0x80,


	.b0_axis = 0x00, .b1_axis = 0x00, .b2_axis = 0x00, .b3_axis = 0x00,
	.b4_axis = 0x00, .b5_axis = 0x00, .b6_axis = 0x00, .b7_axis = 0x00,
	.b8_axis = 0x00, .b9_axis = 0x00, .b10_axis = 0x00, .b11_axis = 0x00,
	.b12_axis = 0x00, .b13_axis = 0x00, .b14_axis = 0x00, .b15_axis = 0x00,
	.b16_axis = 0x00, .b17_axis = 0x00, .b18_axis = 0x00, .b19_axis = 0x00,			
	.b20_axis = 0x00, .b21_axis = 0x00, .b22_axis = 0x00, .b23_axis = 0x00,
	.b24_axis = 0x00, .b25_axis = 0x00, .b26_axis = 0x00, .b27_axis = 0x00,
	.b28_axis = 0x00, .b29_axis = 0x00, .b30_axis = 0x00, .b31_axis = 0x00,
	.b32_axis = 0x00, .b33_axis = 0x00, .b34_axis = 0x00, .b35_axis = 0x00,
	.b36_axis = 0x00, .b37_axis = 0x00, .b38_axis = 0x00, .b39_axis = 0x00,
	.b40_axis = 0x00, .b41_axis = 0x00, .b42_axis = 0x00, .b43_axis = 0x00,
	.b44_axis = 0x00, .b45_axis = 0x00, .b46_axis = 0x00, .b47_axis = 0x00,
	.b48_axis = 0x00, .b49_axis = 0x00, .b50_axis = 0x00, .b51_axis = 0x00,
	.b52_axis = 0x00, .b53_axis = 0x00, .b54_axis = 0x00, .b55_axis = 0x00,
	.b56_axis = 0x00, .b57_axis = 0x00, .b58_axis = 0x00, .b59_axis = 0x00,
	.b60_axis = 0x00, .b61_axis = 0x00, .b62_axis = 0x00, .b63_axis = 0x00,
	.b64_axis = 0x00, .b65_axis = 0x00, .b66_axis = 0x00, .b67_axis = 0x00,
	.b68_axis = 0x00, .b69_axis = 0x00, .b70_axis = 0x00, .b71_axis = 0x00,
	.b72_axis = 0x00, .b73_axis = 0x00, .b74_axis = 0x00, .b75_axis = 0x00,
	.b76_axis = 0x00, .b77_axis = 0x00, .b78_axis = 0x00, .b79_axis = 0x00,
	.b80_axis = 0x00, .b81_axis = 0x00, .b82_axis = 0x00, .b83_axis = 0x00,
	.b84_axis = 0x00, .b85_axis = 0x00, .b86_axis = 0x00, .b87_axis = 0x00,
	.b88_axis = 0x00, .b89_axis = 0x00, .b90_axis = 0x00, .b91_axis = 0x00,
	.b92_axis = 0x00, .b93_axis = 0x00, .b94_axis = 0x00, .b95_axis = 0x00,
	.b96_axis = 0x00, .b97_axis = 0x00, .b98_axis = 0x00, .b99_axis = 0x00,
	.b100_axis = 0x00, .b101_axis = 0x00, .b102_axis = 0x00, .b103_axis = 0x00,
	.b104_axis = 0x00, .b105_axis = 0x00, .b106_axis = 0x00, .b107_axis = 0x00,
	.b108_axis = 0x00, .b109_axis = 0x00, .b110_axis = 0x00, .b111_axis = 0x00,
	.b112_axis = 0x00, .b113_axis = 0x00, .b114_axis = 0x00, .b115_axis = 0x00,
	.b116_axis = 0x00, .b117_axis = 0x00, .b118_axis = 0x00, .b119_axis = 0x00,
	.b120_axis = 0x00, .b121_axis = 0x00, .b122_axis = 0x00, .b123_axis = 0x00,
	.b124_axis = 0x00, .b125_axis = 0x00, .b126_axis = 0x00, .b127_axis = 0x00
};

/*
 * Series of bytes that appear in control packets right after the HID
 * descriptor is sent to the host. They where discovered by tracing output
 * from a Madcatz SF4 Joystick. Sending these bytes makes the PS button work.
 */
static const uint8_t PROGMEM magic_init_bytes[] = {
	0x21, 0x26, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00
};

static uint8_t gamepad_idle_config = 0;

// protocol setting from the host.  We use exactly the same report
// either way, so this variable only stores the setting since we
// are required to be able to report which setting is in use.
static uint8_t gamepad_protocol = 1;

/**************************************************************************
 *
 *  Public Functions - these are the API intended for the user
 *
 **************************************************************************/

// initialize USB
//  Returns 0 if initialized,
//          1 if it timed out waiting for connection
uint8_t usb_init(void) {
	HW_CONFIG();
	USB_FREEZE();				// enable USB
	PLL_CONFIG();				// config PLL
	// wait a certain amount of time for PLL lock
	unsigned long timeoutCounter = 0;
	while (!(PLLCSR & (1<<PLOCK))){
		_delay_ms(1);
		timeoutCounter++;
		if (timeoutCounter >= USB_TIMEOUT)
			return 1;
	}		
	USB_CONFIG();				// start USB clock
	UDCON = 0;				// enable attach resistor
	usb_configuration = 0;
	UDIEN = (1<<EORSTE)|(1<<SOFE);
	sei();
	return 0;
}

// return 0 if the USB is not configured, or the configuration
// number selected by the HOST
uint8_t usb_configured(void) {
	return usb_configuration;
}

gamepad_state_t gamepad_state;

inline void usb_gamepad_reset_state(void) {
	memcpy_P(&gamepad_state, &gamepad_idle_state, sizeof(gamepad_state_t));
}

// sendPS3Data takes in a PhysicalButtonList data struct,
//  maps the data to the format for our gamepad packet,
//  sends that data out via USB,  and outputs
//  a return code (zero if no problems, one if problems
int8_t sendPS3Data(dataForController_t btnList){
	
	gamepad_state.b0_axis = btnList.bt0On;
	gamepad_state.b1_btn = btnList.bt1On;
	gamepad_state.b2_btn = btnList.bt2On;
	gamepad_state.b3_btn = btnList.bt3On;
	gamepad_state.b4_btn = btnList.bt4On;
	gamepad_state.b5_btn = btnList.bt5On;
	gamepad_state.b6_btn = btnList.bt6On;
	gamepad_state.b7_btn = btnList.bt7On;
	gamepad_state.b8_btn = btnList.bt8On;
	gamepad_state.b9_btn = btnList.bt9On;
	gamepad_state.b10_btn = btnList.bt10On;
	gamepad_state.b11_btn = btnList.bt11On;
	gamepad_state.b12_btn = btnList.bt12On;
	gamepad_state.b13_btn = btnList.bt13On;
	gamepad_state.b14_btn = btnList.bt14On;
	gamepad_state.b15_btn = btnList.bt15On;
	gamepad_state.b16_btn = btnList.bt16On;
	gamepad_state.b17_btn = btnList.bt17On;
	gamepad_state.b18_btn = btnList.bt18On;
	gamepad_state.b19_btn = btnList.bt19On;
	gamepad_state.b20_btn = btnList.bt20On;
	gamepad_state.b21_btn = btnList.bt21On;
	gamepad_state.b22_btn = btnList.bt22On;
	gamepad_state.b23_btn = btnList.bt23On;
	gamepad_state.b24_btn = btnList.bt24On;
	gamepad_state.b25_btn = btnList.bt25On;
	gamepad_state.b26_btn = btnList.bt26On;
	gamepad_state.b27_btn = btnList.bt27On;
	gamepad_state.b28_btn = btnList.bt28On;
	gamepad_state.b29_btn = btnList.bt29On;
	gamepad_state.b30_btn = btnList.bt30On;
	gamepad_state.b31_btn = btnList.bt31On;
	gamepad_state.b32_btn = btnList.bt32On;
	gamepad_state.b33_btn = btnList.bt33On;
	gamepad_state.b34_btn = btnList.bt34On;
	gamepad_state.b35_btn = btnList.bt35On;
	gamepad_state.b36_btn = btnList.bt36On;
	gamepad_state.b37_btn = btnList.bt37On;
	gamepad_state.b38_btn = btnList.bt38On;
	gamepad_state.b39_btn = btnList.bt39On;
	gamepad_state.b40_btn = btnList.bt40On;
	gamepad_state.b41_btn = btnList.bt41On;
	gamepad_state.b42_btn = btnList.bt42On;
	gamepad_state.b43_btn = btnList.bt43On;
	gamepad_state.b44_btn = btnList.bt44On;
	gamepad_state.b45_btn = btnList.bt45On;
	gamepad_state.b46_btn = btnList.bt46On;
	gamepad_state.b47_btn = btnList.bt47On;
	gamepad_state.b48_btn = btnList.bt48On;
	gamepad_state.b49_btn = btnList.bt49On;
	gamepad_state.b50_btn = btnList.bt50On;
	gamepad_state.b51_btn = btnList.bt51On;
	gamepad_state.b52_btn = btnList.bt52On;
	gamepad_state.b53_btn = btnList.bt53On;
	gamepad_state.b54_btn = btnList.bt54On;
	gamepad_state.b55_btn = btnList.bt55On;
	gamepad_state.b56_btn = btnList.bt56On;
	gamepad_state.b57_btn = btnList.bt57On;
	gamepad_state.b58_btn = btnList.bt58On;
	gamepad_state.b59_btn = btnList.bt59On;
	gamepad_state.b60_btn = btnList.bt60On;
	gamepad_state.b61_btn = btnList.bt61On;
	gamepad_state.b62_btn = btnList.bt62On;
	gamepad_state.b63_btn = btnList.bt63On;
	gamepad_state.b64_btn = btnList.bt64On;
	gamepad_state.b65_btn = btnList.bt65On;
	gamepad_state.b66_btn = btnList.bt66On;
	gamepad_state.b67_btn = btnList.bt67On;
	gamepad_state.b68_btn = btnList.bt68On;
	gamepad_state.b69_btn = btnList.bt69On;
	gamepad_state.b70_btn = btnList.bt70On;
	gamepad_state.b71_btn = btnList.bt71On;
	gamepad_state.b72_btn = btnList.bt72On;
	gamepad_state.b73_btn = btnList.bt73On;
	gamepad_state.b74_btn = btnList.bt74On;
	gamepad_state.b75_btn = btnList.bt75On;
	gamepad_state.b76_btn = btnList.bt76On;
	gamepad_state.b77_btn = btnList.bt77On;
	gamepad_state.b78_btn = btnList.bt78On;
	gamepad_state.b79_btn = btnList.bt79On;
	gamepad_state.b80_btn = btnList.bt80On;
	gamepad_state.b81_btn = btnList.bt81On;
	gamepad_state.b82_btn = btnList.bt82On;
	gamepad_state.b83_btn = btnList.bt83On;
	gamepad_state.b84_btn = btnList.bt84On;
	gamepad_state.b85_btn = btnList.bt85On;
	gamepad_state.b86_btn = btnList.bt86On;
	gamepad_state.b87_btn = btnList.bt87On;
	gamepad_state.b88_btn = btnList.bt88On;
	gamepad_state.b89_btn = btnList.bt89On;
	gamepad_state.b90_btn = btnList.bt90On;
	gamepad_state.b91_btn = btnList.bt91On;
	gamepad_state.b92_btn = btnList.bt92On;
	gamepad_state.b93_btn = btnList.bt93On;
	gamepad_state.b94_btn = btnList.bt94On;
	gamepad_state.b95_btn = btnList.bt95On;
	gamepad_state.b96_btn = btnList.bt96On;
	gamepad_state.b97_btn = btnList.bt97On;
	gamepad_state.b98_btn = btnList.bt98On;
	gamepad_state.b99_btn = btnList.bt99On;
	gamepad_state.b100_btn = btnList.bt100On;
	gamepad_state.b101_btn = btnList.bt101On;
	gamepad_state.b102_btn = btnList.bt102On;
	gamepad_state.b103_btn = btnList.bt103On;
	gamepad_state.b104_btn = btnList.bt104On;
	gamepad_state.b105_btn = btnList.bt105On;
	gamepad_state.b106_btn = btnList.bt106On;
	gamepad_state.b107_btn = btnList.bt107On;
	gamepad_state.b108_btn = btnList.bt108On;
	gamepad_state.b109_btn = btnList.bt109On;
	gamepad_state.b110_btn = btnList.bt110On;
	gamepad_state.b111_btn = btnList.bt111On;
	gamepad_state.b112_btn = btnList.bt112On;
	gamepad_state.b113_btn = btnList.bt113On;
	gamepad_state.b114_btn = btnList.bt114On;
	gamepad_state.b115_btn = btnList.bt115On;
	gamepad_state.b116_btn = btnList.bt116On;
	gamepad_state.b117_btn = btnList.bt117On;
	gamepad_state.b118_btn = btnList.bt118On;
	gamepad_state.b119_btn = btnList.bt119On;
	gamepad_state.b120_btn = btnList.bt120On;
	gamepad_state.b121_btn = btnList.bt121On;
	gamepad_state.b122_btn = btnList.bt122On;
	gamepad_state.b123_btn = btnList.bt123On;
	gamepad_state.b124_btn = btnList.bt124On;
	gamepad_state.b125_btn = btnList.bt125On;
	gamepad_state.b126_btn = btnList.bt126On;
	gamepad_state.b127_btn = btnList.bt127On;
	
		
	
	if (gamepad_state.b0_btn == 1)
	gamepad_state.b0_axis = 0x01;            // I CHANGED ALL THESE FROM 0xFF to 0x01 (for 1 bit output) IS THIS WRONG?
	else
	gamepad_state.b0_axis = 0;
	
	if (gamepad_state.b1_btn == 1)
	gamepad_state.b1_axis = 0x01;
	else
	gamepad_state.b1_axis = 0;

	if (gamepad_state.b2_btn == 1)
	gamepad_state.b2_axis = 0x01;
	else
	gamepad_state.b2_axis = 0;

	if (gamepad_state.b3_btn == 1)
	gamepad_state.b3_axis = 0x01;
	else
	gamepad_state.b3_axis = 0;

	if (gamepad_state.b4_btn == 1)
	gamepad_state.b4_axis = 0x01;
	else
	gamepad_state.b4_axis = 0;
	
	if (gamepad_state.b5_btn == 1)
	gamepad_state.b5_axis = 0x01;
	else
	gamepad_state.b5_axis = 0;
	
	if (gamepad_state.b6_btn == 1)
	gamepad_state.b6_axis = 0x01;
	else
	gamepad_state.b6_axis = 0;
	
	if (gamepad_state.b7_btn == 1)
	gamepad_state.b7_axis = 0x01;
	else
	gamepad_state.b7_axis = 0;
	
	if (gamepad_state.b8_btn == 1)
	gamepad_state.b8_axis = 0x01;
	else
	gamepad_state.b8_axis = 0;
	
	if (gamepad_state.b9_btn == 1)
	gamepad_state.b9_axis = 0x01;
	else
	gamepad_state.b9_axis = 0;

	if (gamepad_state.b10_btn == 1)
	gamepad_state.b10_axis = 0x01;
	else
	gamepad_state.b10_axis = 0;
	
	if (gamepad_state.b11_btn == 1)
	gamepad_state.b11_axis = 0x01;
	else
	gamepad_state.b11_axis = 0;

	if (gamepad_state.b12_btn == 1)
	gamepad_state.b12_axis = 0x01;
	else
	gamepad_state.b12_axis = 0;

	if (gamepad_state.b13_btn == 1)
	gamepad_state.b13_axis = 0x01;
	else
	gamepad_state.b13_axis = 0;

	if (gamepad_state.b14_btn == 1)
	gamepad_state.b14_axis = 0x01;
	else
	gamepad_state.b14_axis = 0;
	
	if (gamepad_state.b15_btn == 1)
	gamepad_state.b15_axis = 0x01;
	else
	gamepad_state.b15_axis = 0;
	
	if (gamepad_state.b16_btn == 1)
	gamepad_state.b16_axis = 0x01;
	else
	gamepad_state.b16_axis = 0;
	
	if (gamepad_state.b17_btn == 1)
	gamepad_state.b17_axis = 0x01;
	else
	gamepad_state.b17_axis = 0;
	
	if (gamepad_state.b18_btn == 1)
	gamepad_state.b18_axis = 0x01;
	else
	gamepad_state.b18_axis = 0;
	
	if (gamepad_state.b19_btn == 1)
	gamepad_state.b19_axis = 0x01;
	else
	gamepad_state.b19_axis = 0;

	if (gamepad_state.b20_btn == 1)
	gamepad_state.b20_axis = 0x01;
	else
	gamepad_state.b20_axis = 0;
	
	if (gamepad_state.b21_btn == 1)
	gamepad_state.b21_axis = 0x01;
	else
	gamepad_state.b21_axis = 0;

	if (gamepad_state.b22_btn == 1)
	gamepad_state.b22_axis = 0x01;
	else
	gamepad_state.b22_axis = 0;

	if (gamepad_state.b23_btn == 1)
	gamepad_state.b23_axis = 0x01;
	else
	gamepad_state.b23_axis = 0;

	if (gamepad_state.b24_btn == 1)
	gamepad_state.b24_axis = 0x01;
	else
	gamepad_state.b24_axis = 0;
	
	if (gamepad_state.b25_btn == 1)
	gamepad_state.b25_axis = 0x01;
	else
	gamepad_state.b25_axis = 0;
	
	if (gamepad_state.b26_btn == 1)
	gamepad_state.b26_axis = 0x01;
	else
	gamepad_state.b26_axis = 0;
	
	if (gamepad_state.b27_btn == 1)
	gamepad_state.b27_axis = 0x01;
	else
	gamepad_state.b27_axis = 0;
	
	if (gamepad_state.b28_btn == 1)
	gamepad_state.b28_axis = 0x01;
	else
	gamepad_state.b28_axis = 0;
	
	if (gamepad_state.b29_btn == 1)
	gamepad_state.b29_axis = 0x01;
	else
	gamepad_state.b29_axis = 0;

	if (gamepad_state.b30_btn == 1)
	gamepad_state.b30_axis = 0x01;
	else
	gamepad_state.b30_axis = 0;
	
	if (gamepad_state.b31_btn == 1)
	gamepad_state.b31_axis = 0x01;
	else
	gamepad_state.b31_axis = 0;

	if (gamepad_state.b32_btn == 1)
	gamepad_state.b32_axis = 0x01;
	else
	gamepad_state.b32_axis = 0;

	if (gamepad_state.b33_btn == 1)
	gamepad_state.b33_axis = 0x01;
	else
	gamepad_state.b33_axis = 0;

	if (gamepad_state.b34_btn == 1)
	gamepad_state.b34_axis = 0x01;
	else
	gamepad_state.b34_axis = 0;
	
	if (gamepad_state.b35_btn == 1)
	gamepad_state.b35_axis = 0x01;
	else
	gamepad_state.b35_axis = 0;
	
	if (gamepad_state.b36_btn == 1)
	gamepad_state.b36_axis = 0x01;
	else
	gamepad_state.b36_axis = 0;
	
	if (gamepad_state.b37_btn == 1)
	gamepad_state.b37_axis = 0x01;
	else
	gamepad_state.b37_axis = 0;
	
	if (gamepad_state.b38_btn == 1)
	gamepad_state.b38_axis = 0x01;
	else
	gamepad_state.b38_axis = 0;
	
	if (gamepad_state.b39_btn == 1)
	gamepad_state.b39_axis = 0x01;
	else
	gamepad_state.b39_axis = 0;

	if (gamepad_state.b40_btn == 1)
	gamepad_state.b40_axis = 0x01;
	else
	gamepad_state.b40_axis = 0;
	
	if (gamepad_state.b41_btn == 1)
	gamepad_state.b41_axis = 0x01;
	else
	gamepad_state.b41_axis = 0;

	if (gamepad_state.b42_btn == 1)
	gamepad_state.b42_axis = 0x01;
	else
	gamepad_state.b42_axis = 0;

	if (gamepad_state.b43_btn == 1)
	gamepad_state.b43_axis = 0x01;
	else
	gamepad_state.b43_axis = 0;

	if (gamepad_state.b44_btn == 1)
	gamepad_state.b44_axis = 0x01;
	else
	gamepad_state.b44_axis = 0;
	
	if (gamepad_state.b45_btn == 1)
	gamepad_state.b45_axis = 0x01;
	else
	gamepad_state.b45_axis = 0;
	
	if (gamepad_state.b46_btn == 1)
	gamepad_state.b46_axis = 0x01;
	else
	gamepad_state.b46_axis = 0;
	
	if (gamepad_state.b47_btn == 1)
	gamepad_state.b47_axis = 0x01;
	else
	gamepad_state.b47_axis = 0;
	
	if (gamepad_state.b48_btn == 1)
	gamepad_state.b48_axis = 0x01;
	else
	gamepad_state.b48_axis = 0;
	
	if (gamepad_state.b49_btn == 1)
	gamepad_state.b49_axis = 0x01;
	else
	gamepad_state.b49_axis = 0;

	if (gamepad_state.b50_btn == 1)
	gamepad_state.b50_axis = 0x01;
	else
	gamepad_state.b50_axis = 0;
	
	if (gamepad_state.b51_btn == 1)
	gamepad_state.b51_axis = 0x01;
	else
	gamepad_state.b51_axis = 0;

	if (gamepad_state.b52_btn == 1)
	gamepad_state.b52_axis = 0x01;
	else
	gamepad_state.b52_axis = 0;

	if (gamepad_state.b53_btn == 1)
	gamepad_state.b53_axis = 0x01;
	else
	gamepad_state.b53_axis = 0;

	if (gamepad_state.b54_btn == 1)
	gamepad_state.b54_axis = 0x01;
	else
	gamepad_state.b54_axis = 0;
	
	if (gamepad_state.b55_btn == 1)
	gamepad_state.b55_axis = 0x01;
	else
	gamepad_state.b55_axis = 0;
	
	if (gamepad_state.b56_btn == 1)
	gamepad_state.b56_axis = 0x01;
	else
	gamepad_state.b56_axis = 0;
	
	if (gamepad_state.b57_btn == 1)
	gamepad_state.b57_axis = 0x01;
	else
	gamepad_state.b57_axis = 0;
	
	if (gamepad_state.b58_btn == 1)
	gamepad_state.b58_axis = 0x01;
	else
	gamepad_state.b58_axis = 0;
	
	if (gamepad_state.b59_btn == 1)
	gamepad_state.b59_axis = 0x01;
	else
	gamepad_state.b59_axis = 0;

	if (gamepad_state.b60_btn == 1)
	gamepad_state.b60_axis = 0x01;
	else
	gamepad_state.b60_axis = 0;
	
	if (gamepad_state.b61_btn == 1)
	gamepad_state.b61_axis = 0x01;
	else
	gamepad_state.b61_axis = 0;

	if (gamepad_state.b62_btn == 1)
	gamepad_state.b62_axis = 0x01;
	else
	gamepad_state.b62_axis = 0;

	if (gamepad_state.b63_btn == 1)
	gamepad_state.b63_axis = 0x01;
	else
	gamepad_state.b63_axis = 0;

	if (gamepad_state.b64_btn == 1)
	gamepad_state.b64_axis = 0x01;
	else
	gamepad_state.b64_axis = 0;
	
	if (gamepad_state.b65_btn == 1)
	gamepad_state.b65_axis = 0x01;
	else
	gamepad_state.b65_axis = 0;
	
	if (gamepad_state.b66_btn == 1)
	gamepad_state.b66_axis = 0x01;
	else
	gamepad_state.b66_axis = 0;
	
	if (gamepad_state.b67_btn == 1)
	gamepad_state.b67_axis = 0x01;
	else
	gamepad_state.b67_axis = 0;
	
	if (gamepad_state.b68_btn == 1)
	gamepad_state.b68_axis = 0x01;
	else
	gamepad_state.b68_axis = 0;
	
	if (gamepad_state.b69_btn == 1)
	gamepad_state.b69_axis = 0x01;
	else
	gamepad_state.b69_axis = 0;

	if (gamepad_state.b70_btn == 1)
	gamepad_state.b70_axis = 0x01;
	else
	gamepad_state.b70_axis = 0;
	
	if (gamepad_state.b71_btn == 1)
	gamepad_state.b71_axis = 0x01;
	else
	gamepad_state.b71_axis = 0;

	if (gamepad_state.b72_btn == 1)
	gamepad_state.b72_axis = 0x01;
	else
	gamepad_state.b72_axis = 0;

	if (gamepad_state.b73_btn == 1)
	gamepad_state.b73_axis = 0x01;
	else
	gamepad_state.b73_axis = 0;

	if (gamepad_state.b74_btn == 1)
	gamepad_state.b74_axis = 0x01;
	else
	gamepad_state.b74_axis = 0;
	
	if (gamepad_state.b75_btn == 1)
	gamepad_state.b75_axis = 0x01;
	else
	gamepad_state.b75_axis = 0;
	
	if (gamepad_state.b76_btn == 1)
	gamepad_state.b76_axis = 0x01;
	else
	gamepad_state.b76_axis = 0;
	
	if (gamepad_state.b77_btn == 1)
	gamepad_state.b77_axis = 0x01;
	else
	gamepad_state.b77_axis = 0;
	
	if (gamepad_state.b78_btn == 1)
	gamepad_state.b78_axis = 0x01;
	else
	gamepad_state.b78_axis = 0;
	
	if (gamepad_state.b79_btn == 1)
	gamepad_state.b79_axis = 0x01;
	else
	gamepad_state.b79_axis = 0;

	if (gamepad_state.b80_btn == 1)
	gamepad_state.b80_axis = 0x01;
	else
	gamepad_state.b80_axis = 0;
	
	if (gamepad_state.b81_btn == 1)
	gamepad_state.b81_axis = 0x01;
	else
	gamepad_state.b81_axis = 0;

	if (gamepad_state.b82_btn == 1)
	gamepad_state.b82_axis = 0x01;
	else
	gamepad_state.b82_axis = 0;

	if (gamepad_state.b83_btn == 1)
	gamepad_state.b83_axis = 0x01;
	else
	gamepad_state.b83_axis = 0;

	if (gamepad_state.b84_btn == 1)
	gamepad_state.b84_axis = 0x01;
	else
	gamepad_state.b84_axis = 0;
	
	if (gamepad_state.b85_btn == 1)
	gamepad_state.b85_axis = 0x01;
	else
	gamepad_state.b85_axis = 0;
	
	if (gamepad_state.b86_btn == 1)
	gamepad_state.b86_axis = 0x01;
	else
	gamepad_state.b86_axis = 0;
	
	if (gamepad_state.b87_btn == 1)
	gamepad_state.b87_axis = 0x01;
	else
	gamepad_state.b87_axis = 0;
	
	if (gamepad_state.b88_btn == 1)
	gamepad_state.b88_axis = 0x01;
	else
	gamepad_state.b88_axis = 0;
	
	if (gamepad_state.b89_btn == 1)
	gamepad_state.b89_axis = 0x01;
	else
	gamepad_state.b89_axis = 0;

	if (gamepad_state.b90_btn == 1)
	gamepad_state.b90_axis = 0x01;
	else
	gamepad_state.b90_axis = 0;
	
	if (gamepad_state.b91_btn == 1)
	gamepad_state.b91_axis = 0x01;
	else
	gamepad_state.b91_axis = 0;

	if (gamepad_state.b92_btn == 1)
	gamepad_state.b92_axis = 0x01;
	else
	gamepad_state.b92_axis = 0;

	if (gamepad_state.b93_btn == 1)
	gamepad_state.b93_axis = 0x01;
	else
	gamepad_state.b93_axis = 0;

	if (gamepad_state.b94_btn == 1)
	gamepad_state.b94_axis = 0x01;
	else
	gamepad_state.b94_axis = 0;
	
	if (gamepad_state.b95_btn == 1)
	gamepad_state.b95_axis = 0x01;
	else
	gamepad_state.b95_axis = 0;
	
	if (gamepad_state.b96_btn == 1)
	gamepad_state.b96_axis = 0x01;
	else
	gamepad_state.b96_axis = 0;
	
	if (gamepad_state.b97_btn == 1)
	gamepad_state.b97_axis = 0x01;
	else
	gamepad_state.b97_axis = 0;
	
	if (gamepad_state.b98_btn == 1)
	gamepad_state.b98_axis = 0x01;
	else
	gamepad_state.b98_axis = 0;
	
	if (gamepad_state.b99_btn == 1)
	gamepad_state.b99_axis = 0x01;
	else
	gamepad_state.b99_axis = 0;

	if (gamepad_state.b100_btn == 1)
	gamepad_state.b100_axis = 0x01;
	else
	gamepad_state.b100_axis = 0;
	
	if (gamepad_state.b101_btn == 1)
	gamepad_state.b101_axis = 0x01;
	else
	gamepad_state.b101_axis = 0;

	if (gamepad_state.b102_btn == 1)
	gamepad_state.b102_axis = 0x01;
	else
	gamepad_state.b102_axis = 0;

	if (gamepad_state.b103_btn == 1)
	gamepad_state.b103_axis = 0x01;
	else
	gamepad_state.b103_axis = 0;

	if (gamepad_state.b104_btn == 1)
	gamepad_state.b104_axis = 0x01;
	else
	gamepad_state.b104_axis = 0;
	
	if (gamepad_state.b105_btn == 1)
	gamepad_state.b105_axis = 0x01;
	else
	gamepad_state.b105_axis = 0;
	
	if (gamepad_state.b106_btn == 1)
	gamepad_state.b106_axis = 0x01;
	else
	gamepad_state.b106_axis = 0;
	
	if (gamepad_state.b107_btn == 1)
	gamepad_state.b107_axis = 0x01;
	else
	gamepad_state.b107_axis = 0;
	
	if (gamepad_state.b108_btn == 1)
	gamepad_state.b108_axis = 0x01;
	else
	gamepad_state.b108_axis = 0;
	
	if (gamepad_state.b109_btn == 1)
	gamepad_state.b109_axis = 0x01;
	else
	gamepad_state.b109_axis = 0;

	if (gamepad_state.b110_btn == 1)
	gamepad_state.b110_axis = 0x01;
	else
	gamepad_state.b110_axis = 0;
	
	if (gamepad_state.b111_btn == 1)
	gamepad_state.b111_axis = 0x01;
	else
	gamepad_state.b111_axis = 0;

	if (gamepad_state.b112_btn == 1)
	gamepad_state.b112_axis = 0x01;
	else
	gamepad_state.b112_axis = 0;

	if (gamepad_state.b113_btn == 1)
	gamepad_state.b113_axis = 0x01;
	else
	gamepad_state.b113_axis = 0;

	if (gamepad_state.b114_btn == 1)
	gamepad_state.b114_axis = 0x01;
	else
	gamepad_state.b114_axis = 0;
	
	if (gamepad_state.b115_btn == 1)
	gamepad_state.b115_axis = 0x01;
	else
	gamepad_state.b115_axis = 0;
	
	if (gamepad_state.b116_btn == 1)
	gamepad_state.b116_axis = 0x01;
	else
	gamepad_state.b116_axis = 0;
	
	if (gamepad_state.b117_btn == 1)
	gamepad_state.b117_axis = 0x01;
	else
	gamepad_state.b117_axis = 0;
	
	if (gamepad_state.b118_btn == 1)
	gamepad_state.b118_axis = 0x01;
	else
	gamepad_state.b118_axis = 0;
	
	if (gamepad_state.b119_btn == 1)
	gamepad_state.b119_axis = 0x01;
	else
	gamepad_state.b119_axis = 0;

	if (gamepad_state.b120_btn == 1)
	gamepad_state.b120_axis = 0x01;
	else
	gamepad_state.b120_axis = 0;
	
	if (gamepad_state.b121_btn == 1)
	gamepad_state.b121_axis = 0x01;
	else
	gamepad_state.b121_axis = 0;

	if (gamepad_state.b122_btn == 1)
	gamepad_state.b122_axis = 0x01;
	else
	gamepad_state.b122_axis = 0;

	if (gamepad_state.b123_btn == 1)
	gamepad_state.b123_axis = 0x01;
	else
	gamepad_state.b123_axis = 0;

	if (gamepad_state.b124_btn == 1)
	gamepad_state.b124_axis = 0x01;
	else
	gamepad_state.b124_axis = 0;
	
	if (gamepad_state.b125_btn == 1)
	gamepad_state.b125_axis = 0x01;
	else
	gamepad_state.b125_axis = 0;
	
	if (gamepad_state.b126_btn == 1)
	gamepad_state.b126_axis = 0x01;
	else
	gamepad_state.b126_axis = 0;
	
	if (gamepad_state.b127_btn == 1)
	gamepad_state.b127_axis = 0x01;
	else
	gamepad_state.b127_axis = 0;
	

	// left and right analog sticks, 0x00 left/up, 0x80 middle, 0xff right/down

	gamepad_state.a0_axis = btnList.al0;
	gamepad_state.a1_axis = btnList.al1;
	gamepad_state.a2_axis = btnList.al2;
	gamepad_state.a3_axis = btnList.al3;
	gamepad_state.a4_axis = btnList.al4;
	gamepad_state.a5_axis = btnList.al5;		
	gamepad_state.a6_axis = btnList.al6;
	gamepad_state.a7_axis = btnList.al7;
	gamepad_state.a8_axis = btnList.al8;
	gamepad_state.a9_axis = btnList.al9;
	gamepad_state.a10_axis = btnList.al10;
	gamepad_state.a11_axis = btnList.al11;
	gamepad_state.a12_axis = btnList.al12;
	gamepad_state.a13_axis = btnList.al13;
	gamepad_state.a14_axis = btnList.al14;
	gamepad_state.a15_axis = btnList.al15;
	gamepad_state.a16_axis = btnList.al16;
	gamepad_state.a17_axis = btnList.al17;
	gamepad_state.a18_axis = btnList.al18;
	gamepad_state.a19_axis = btnList.al19;
	gamepad_state.a20_axis = btnList.al10;
	gamepad_state.a21_axis = btnList.al21;
	gamepad_state.a22_axis = btnList.al22;
	gamepad_state.a23_axis = btnList.al23;
	gamepad_state.a24_axis = btnList.al24;
	gamepad_state.a25_axis = btnList.al25;
	gamepad_state.a26_axis = btnList.al26;
	gamepad_state.a27_axis = btnList.al27;
	gamepad_state.a28_axis = btnList.al28;
	gamepad_state.a29_axis = btnList.al29;
	gamepad_state.a30_axis = btnList.al30;
	gamepad_state.a31_axis = btnList.al31;
	gamepad_state.a32_axis = btnList.al32;
	gamepad_state.a33_axis = btnList.al33;
	gamepad_state.a34_axis = btnList.al34;
	gamepad_state.a35_axis = btnList.al35;
	gamepad_state.a36_axis = btnList.al36;
	gamepad_state.a37_axis = btnList.al37;
	gamepad_state.a38_axis = btnList.al38;
	gamepad_state.a39_axis = btnList.al39;
	gamepad_state.a40_axis = btnList.al40;
	gamepad_state.a41_axis = btnList.al41;
	gamepad_state.a42_axis = btnList.al42;
	gamepad_state.a43_axis = btnList.al43;
	gamepad_state.a44_axis = btnList.al44;
	gamepad_state.a45_axis = btnList.al45;
	gamepad_state.a46_axis = btnList.al46;
	gamepad_state.a47_axis = btnList.al47;
	
	
	// Send the data out via USB
	return usb_gamepad_send();
}

int8_t usb_gamepad_send(void) {
	uint8_t intr_state, timeout, i;

	if (!usb_configuration) return -1;
	intr_state = SREG;
	cli();
	UENUM = GAMEPAD_ENDPOINT;
	timeout = UDFNUML + 50;
	while (1) {
		// are we ready to transmit?
		if (UEINTX & (1<<RWAL)) break;
		SREG = intr_state;
		// has the USB gone offline?
		if (!usb_configuration) return -1;
		// have we waited too long?
		if (UDFNUML == timeout) return -1;
		// get ready to try checking again
		intr_state = SREG;
		cli();
		UENUM = GAMEPAD_ENDPOINT;
	}

	for (i=0; i<sizeof(gamepad_state_t); i++) {
		UEDATX = ((uint8_t*)&gamepad_state)[i];
	}

	UEINTX = 0x3A;
	SREG = intr_state;
	return 0;
}

/**************************************************************************
 *
 *  Private Functions - not intended for general user consumption....
 *
 **************************************************************************/

ISR(USB_GEN_vect)
{
	uint8_t intbits;

	intbits = UDINT;
	UDINT = 0;
	if (intbits & (1<<EORSTI)) {
		UENUM = 0;
		UECONX = 1;
		UECFG0X = EP_TYPE_CONTROL;
		UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
		UEIENX = (1<<RXSTPE);
		usb_configuration = 0;
	}
}

// Misc functions to wait for ready and send/receive packets
static inline void usb_wait_in_ready(void)
{
	while (!(UEINTX & (1<<TXINI))) ;
}
static inline void usb_send_in(void)
{
	UEINTX = ~(1<<TXINI);
}
static inline void usb_wait_receive_out(void)
{
	while (!(UEINTX & (1<<RXOUTI))) ;
}
static inline void usb_ack_out(void)
{
	UEINTX = ~(1<<RXOUTI);
}

// USB Endpoint Interrupt - endpoint 0 is handled here.  The
// other endpoints are manipulated by the user-callable
// functions, and the start-of-frame interrupt.
//
ISR(USB_COM_vect)
{
	uint8_t intbits;
	const uint8_t *list;
	const uint8_t *cfg;
	uint8_t i, n, len, en;
	uint8_t bmRequestType;
	uint8_t bRequest;
	uint16_t wValue;
	uint16_t wIndex;
	uint16_t wLength;
	uint16_t desc_val;
	const uint8_t *desc_addr;
	uint8_t	desc_length;

	UENUM = 0;
	intbits = UEINTX;
	if (intbits & (1<<RXSTPI)) {
		bmRequestType = UEDATX;
		bRequest = UEDATX;
		wValue = UEDATX;
		wValue |= (UEDATX << 8);
		wIndex = UEDATX;
		wIndex |= (UEDATX << 8);
		wLength = UEDATX;
		wLength |= (UEDATX << 8);
		UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
		if (bRequest == GET_DESCRIPTOR) {
			list = (const uint8_t *)descriptor_list;
			for (i=0; ; i++) {
				if (i >= NUM_DESC_LIST) {
					UECONX = (1<<STALLRQ)|(1<<EPEN);  //stall
					return;
				}
				desc_val = pgm_read_word(list);
				if (desc_val != wValue) {
					list += sizeof(struct descriptor_list_struct);
					continue;
				}
				list += 2;
				desc_val = pgm_read_word(list);
				if (desc_val != wIndex) {
					list += sizeof(struct descriptor_list_struct)-2;
					continue;
				}
				list += 2;
				desc_addr = (const uint8_t *)pgm_read_word(list);
				list += 2;
				desc_length = pgm_read_byte(list);
				break;
			}
			len = (wLength < 256) ? wLength : 255;
			if (len > desc_length) len = desc_length;
			do {
				// wait for host ready for IN packet
				do {
					i = UEINTX;
				} while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
				if (i & (1<<RXOUTI)) return;	// abort
				// send IN packet
				n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
				for (i = n; i; i--) {
					UEDATX = pgm_read_byte(desc_addr++);
				}
				len -= n;
				usb_send_in();
			} while (len || n == ENDPOINT0_SIZE);
			return;
		}
		if (bRequest == SET_ADDRESS) {
			usb_send_in();
			usb_wait_in_ready();
			UDADDR = wValue | (1<<ADDEN);
			return;
		}
		if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
			usb_configuration = wValue;
			usb_send_in();
			cfg = endpoint_config_table;
			for (i=1; i<5; i++) {
				UENUM = i;
				en = pgm_read_byte(cfg++);
				UECONX = en;
				if (en) {
					UECFG0X = pgm_read_byte(cfg++);
					UECFG1X = pgm_read_byte(cfg++);
				}
			}
			UERST = 0x1E;
			UERST = 0;
			return;
		}
		if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
			usb_wait_in_ready();
			UEDATX = usb_configuration;
			usb_send_in();
			return;
		}

		if (bRequest == GET_STATUS) {
			usb_wait_in_ready();
			i = 0;
			#ifdef SUPPORT_ENDPOINT_HALT
			if (bmRequestType == 0x82) {
				UENUM = wIndex;
				if (UECONX & (1<<STALLRQ)) i = 1;
				UENUM = 0;
			}
			#endif
			UEDATX = i;
			UEDATX = 0;
			usb_send_in();
			return;
		}
		#ifdef SUPPORT_ENDPOINT_HALT
		if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
		  && bmRequestType == 0x02 && wValue == 0) {
			i = wIndex & 0x7F;
			if (i >= 1 && i <= MAX_ENDPOINT) {
				usb_send_in();
				UENUM = i;
				if (bRequest == SET_FEATURE) {
					UECONX = (1<<STALLRQ)|(1<<EPEN);
				} else {
					UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
					UERST = (1 << i);
					UERST = 0;
				}
				return;
			}
		}
		#endif
		if (wIndex == GAMEPAD_INTERFACE) {
			if (bmRequestType == 0xA1) {
				if (bRequest == HID_GET_REPORT) {
					usb_wait_in_ready();

					for (i=0; i<sizeof(magic_init_bytes); i++) {
						UEDATX = pgm_read_byte(&magic_init_bytes[i]);
					}

					usb_send_in();
					return;
				}
				if (bRequest == HID_GET_IDLE) {
					usb_wait_in_ready();
					UEDATX = gamepad_idle_config;
					usb_send_in();
					return;
				}
				if (bRequest == HID_GET_PROTOCOL) {
					usb_wait_in_ready();
					UEDATX = gamepad_protocol;
					usb_send_in();
					return;
				}
			}
			if (bmRequestType == 0x21) {
				if (bRequest == HID_SET_REPORT) {
					usb_wait_receive_out();
					usb_ack_out();
					usb_send_in();
					return;
				}
				if (bRequest == HID_SET_IDLE) {
					gamepad_idle_config = (wValue >> 8);
					usb_send_in();
					return;
				}
				if (bRequest == HID_SET_PROTOCOL) {
					gamepad_protocol = wValue;
					usb_send_in();
					return;
				}
			}
		}
	}
	UECONX = (1<<STALLRQ) | (1<<EPEN);	// stall
}


